﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.VisualStudio.TextTemplating;
using System.CodeDom.Compiler;
using System.Xml;
using System.Data.Metadata.Edm;
using System.Collections.ObjectModel;
using System.Data.Mapping;
using System.Data.Objects; 

namespace RBTools.CodeGenerator.T4Generator.Consoles
{
    class Program
    {
        static void Main(string[] args)
        {
            TestEntity();
            string pathToDataFolder = @"C:\CodeGenerators\Templates\1";
            MetadataWorkspace metdataWorkspace = new MetadataWorkspace();
            EdmItemCollection edmItemCollection = new EdmItemCollection(pathToDataFolder);
            metdataWorkspace.RegisterItemCollection(edmItemCollection);

            StoreItemCollection storeItemCollection = new StoreItemCollection(pathToDataFolder);
            metdataWorkspace.RegisterItemCollection(storeItemCollection);

            StorageMappingItemCollection storageMappingItemCollection = new StorageMappingItemCollection(edmItemCollection, storeItemCollection, pathToDataFolder);
            metdataWorkspace.RegisterItemCollection(storageMappingItemCollection);

            GetItemsFromModel(metdataWorkspace, DataSpace.OSpace);

            GetItemsFromModel(metdataWorkspace, DataSpace.SSpace);
            GetItemsFromModel(metdataWorkspace, DataSpace.OCSpace);

            //MetadataItemCollectionFactory

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("Model1.extedmx");
            StringBuilder pathBuilder = new StringBuilder();
            pathBuilder.AppendFormat("/extedmx/Entities/{0}/{1}/Attributes/Add[@name='{2}']","Page","TenantID","StaticConstraintAttribute");
            XmlNode node = xmlDoc.SelectSingleNode(pathBuilder.ToString());

            try
            {
                args = new string[] { @"C:\CodeGenerators\Templates\EntityFramework\CSharpEntityModel.tt" };
                ProcessTemplate(args);
                Console.WriteLine("Success!");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();
        }

        static void GetItemsFromModel(MetadataWorkspace workspace, DataSpace dataSpace)
        {
            ReadOnlyCollection<EdmType> types = workspace.GetItems<EdmType>(dataSpace);
            foreach (var type in types)
            {
                string name = type.Name;
            }
        }
        static void ProcessTemplate(string[] args)
        {
            string TemplateFileName = null;
            string NamespaceSuggestion = "ddddd";
            if (args.Length <= 0)
            {
                throw new Exception("You must provide a text template file path!");
            }
            TemplateFileName = args[0];
            if (TemplateFileName == null)
            {
                throw new ArgumentNullException("the file name cannot be null!");
            }
            if (!File.Exists(TemplateFileName))
            {
                throw new FileNotFoundException("the file cannot be found!");
            }

            ExtedmxTextTemplatingEngineHost host = new ExtedmxTextTemplatingEngineHost();
            Engine engine = new Engine();
            host.TemplateFile = TemplateFileName;
            host.NamespaceSuggestion = NamespaceSuggestion;

            //Read the text template
            string input = File.ReadAllText(TemplateFileName);

            string edmxDataFilename = @"C:\CodeGenerators\Templates\DBModel.edmx";
            input = input.Replace("$edmxInputFile$", edmxDataFilename);
            input = input.Replace("$namespace$", NamespaceSuggestion);

            //return NamespaceSuggestion +"  "+ edmxDataFilename;
            //Transform the text template
            string output = engine.ProcessTemplate(input, host);

            string outputFileName = Path.GetFileNameWithoutExtension(TemplateFileName);
            outputFileName = outputFileName + "1" + host.OutputFileExtension;

            File.WriteAllText(outputFileName, output, host.OutputFileEncoding);
            foreach (CompilerError error in host.Errors)
            {
                Console.WriteLine(error.ToString());
            }
        }

        static void TestEntity()
        {
            string connectStr = System.Configuration.ConfigurationManager.ConnectionStrings["MDAEntities1"].ConnectionString;
            using (MDAEntities1 entities = new MDAEntities1(connectStr))
            {
                var pages = (from p in entities.Pages.Where(string.Format("{0}.TenantIDDD=@TenantIDDD",entities.Pages.Name), new ObjectParameter("TenantIDDD", 1))
                             where p.ID == 1
                             select p).ToList();
            }
        }
         
        //public class ExtMetadata
        //{
        //    private const string StaticConstraintAttributeName = "StaticConstraintAttribute";
        //    private static readonly XmlDocument xmlDoc = new XmlDocument();
        //    private static string _extMetadataFileName;

        //    public static void Initialize(string extMetadataFileName)
        //    {
        //        _extMetadataFileName = extMetadataFileName;
        //        xmlDoc.Load(extMetadataFileName);
        //    }

        //    public static XmlNode EntityPropertyHasAttribute(EdmMember member, string attributeName)
        //    {
        //        string attributePath = GetAttributePath(member, attributeName);
        //        return xmlDoc.SelectSingleNode(attributePath);
        //    }

        //    public static bool IsPropertyGetProtected(EdmMember member)
        //    {
        //        return false;
        //    }

        //    public static bool IsPropertySetProtected(EdmMember member)
        //    {
        //        return EntityPropertyHasAttribute(member, StaticConstraintAttributeName) != null;
        //    }

        //    private static string GetAttributePath(EdmMember member, string attributeName)
        //    {
        //        StringBuilder pathBuilder = new StringBuilder();
        //        pathBuilder.AppendFormat("/extedmx/Entities/Entity[@name='{0}']/properties/property[@name='{1}']/Attributes/Add[@name='{2}']", member.DeclaringType.Name, member.Name, attributeName);
        //        return pathBuilder.ToString();
        //    }

        //    private static string GetPropertyXPath(EdmMember member)
        //    {
        //        StringBuilder pathBuilder = new StringBuilder();
        //        pathBuilder.AppendFormat("/extedmx/Entities/Entity[@name='{0}']/properties/property[@name='{1}']", member.DeclaringType.Name, member.Name);
        //        return pathBuilder.ToString();
        //    }

        //    public static List<string> GetExtCustomAttributes(EdmMember member)
        //    {
        //List<string> allAttributes = new List<string>();
        //string memberAttrsXPath = ExtMetadata.GetPropertyXPath(member+"/Attributes");
        //if (!String.IsNullOrEmpty(memberAttrsXPath))
        //{
        //    XmlNode memberAttrsNode = xmlDoc.SelectSingleNode(memberAttrsXPath);
        //    if (memberAttrsNode != null)
        //    {
        //        foreach (XmlElement attrNode in memberAttrsNode.ChildNodes)
        //        {
        //            allAttributes.Add(attrNode.GetAttribute("name"));
        //        }
        //    }
        //}
        //return allAttributes;
        //    }
        //}

        public class ExtMetadataLoader
        {
            private readonly DynamicTextTransformation _textTransformation;
            public ExtMetadataLoader(object textTransformation)
            {
                if (textTransformation == null)
                {
                    throw new ArgumentNullException("Arguement cannot be NULL.");
                }
                this._textTransformation = DynamicTextTransformation.Create(textTransformation);
            }
        }

        public class DynamicTextTransformation
        {
            private DynamicTextTransformation(object instance)
            { 
            }

            public static DynamicTextTransformation Create(object instance)
            {
                return new DynamicTextTransformation(instance);
            }
        }
    }

    public class StaticConstraintAttribute:Attribute
    {
        public StaticConstraintAttribute()
        { 
        }
    }
}
